package org.zh.client.jdbc;

import org.zh.util.HashMap_;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;



public class TCCache {
    private static final HashMap_<String, Class<?>, TableInfo> cache = new HashMap_<>();


    public static void initCache(Connection conn, String tableName, Class<?> beanClass) throws SQLException {
        String sql = "select * from " + tableName + " limit 1";
        Statement statement = conn.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        ResultSetMetaData metaData = rs.getMetaData();
        int count = metaData.getColumnCount();
        TableInfo ti = null;
        Map<String, String> ct = new HashMap<>();
        for (int i = 0; i < count; i++) {
            String columnName = metaData.getColumnName(i + 1);
            String fileName = getCamelCase(metaData.getColumnName(i + 1));
            ct.put(columnName, fileName);
            ct.put(fileName, columnName);
        }
        DatabaseMetaData connMetaData = conn.getMetaData();
        ResultSet pk = connMetaData.getPrimaryKeys(conn.getCatalog(), conn.getSchema(), tableName);
        while (pk.next()) {
            if (pk.getString(3).equals(tableName)) {
                ti = new TableInfo(pk.getString(4), ct.get(pk.getString(4)), ct);
            }
        }
        if (ti == null) {
            ti = new TableInfo(null, null, ct);
        }


        cache.put(tableName, beanClass, ti);
        pk.close();
        rs.close();
        statement.close();
        conn.close();

    }

    public static void print() {
        cache.forEach((String k1, Class<?> k2, TableInfo v) -> {
            System.out.println(k1);
            System.out.println(k2);
            System.out.println(v.clazzId());
            System.out.println(v.priKey());
            System.out.println(v.columns().values());
            System.out.println("-----------------------------------");
        });
    }

    public static Map<String, String> getCacheMap(Class<?> clazz) {
        return cache.get(clazz).columns();
    }

    public static Map<String, String> getCacheMap(String tableName) {
        return cache.get(tableName).columns();
    }

    public static String getTableName(Class<?> clazz) {
        return (String) cache.getKey(clazz);
    }

    public static String getFileOrColumn(Class<?> clazz, String fileOrColumn) {
        return cache.get(clazz).columns().get(fileOrColumn);
    }

    public static String getPriKey(String tableName) {
        return cache.get(tableName).priKey();
    }

    public static String getClassId(String tableName) {
        return cache.get(tableName).clazzId();
    }

    public static String getCamelCase(String column) {
        String[] words = column.split("_");
        StringBuilder camelCase = new StringBuilder();
        for (int i = 0; i < words.length; i++) {
            if (i == 0) {
                camelCase.append(words[i]);
            } else {
                camelCase.append(Character.toUpperCase(words[i].charAt(0)));
                if (words[i].length() > 1) {
                    camelCase.append(words[i].substring(1));
                }
            }
        }
        return camelCase.toString();
    }

    public static <T> Map<String, Object> beanToMapRef(T t) throws Throwable {
        Class<?> aClass = t.getClass();
        Map<String, String> ct = getCacheMap(aClass);
        MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(aClass, MethodHandles.lookup());
        Field[] declaredFields = aClass.getDeclaredFields();
        Map<String, Object> data = new HashMap<>();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            MethodHandle getter = lookup.findGetter(aClass, field.getName(), field.getType());
            Object invoke = getter.invoke(t);
            String columnName = ct.get(field.getName());
            data.put(columnName, invoke);
        }
        return data;
    }


}
